# -*- coding: utf-8 -*-
"""
投资组合模块 - 数据模型定义

本文件定义了测试DEMO中投资组合相关的所有数据模型，包括：

1. Portfolio - 投资组合模型
   - 存储用户的投资组合基本信息
   - 支持4:3:2:1资产配置策略（稳健:平衡:成长:进取）
   - 记录投资金额、当前市值和收益情况
   - 提供总收益和收益率的计算属性
   - 支持组合状态管理（活跃、暂停、关闭）

2. PortfolioHolding - 投资组合持仓模型
   - 记录组合中每个产品的持仓详情
   - 包含持有份额、成本价格、当前价格
   - 计算成本金额、当前金额和盈亏情况
   - 提供盈亏金额和盈亏率的计算属性
   - 支持持仓的唯一性约束

3. StopLossSetting - 止损设置模型
   - 为投资组合中的产品配置止损策略
   - 支持三种止损策略：
     * 固定比例止损：基于固定的止损比例
     * 移动止损：跟踪最高价格的动态止损
     * 技术指标止损：基于技术分析指标
   - 支持自动执行和手动执行模式
   - 记录止损状态和触发时间

4. Transaction - 交易记录模型
   - 记录投资组合的所有交易活动
   - 支持买入、卖出、分红等交易类型
   - 详细记录交易份额、价格、金额和手续费
   - 按交易时间排序，便于历史查询

常量定义：
- PORTFOLIO_STATUS: 投资组合状态选项
- STOP_LOSS_STRATEGIES: 止损策略类型选项
- STOP_LOSS_STATUS: 止损状态选项

这些模型构成了完整的投资组合管理体系，支持多元化资产配置、
风险控制和交易记录管理，为用户提供专业的投资组合服务。

Author: zhaozeliang
Date: 2025-09-06
"""

from django.db import models
from django.conf import settings
from decimal import Decimal
from products.models import Product

# 投资组合状态
PORTFOLIO_STATUS = [
    ('active', '活跃'),
    ('suspended', '暂停'),
    ('closed', '关闭'),
]

# 止损策略类型
STOP_LOSS_STRATEGIES = [
    ('fixed_ratio', '固定比例止损'),
    ('trailing', '移动止损'),
    ('technical', '技术指标止损'),
]

# 止损状态
STOP_LOSS_STATUS = [
    ('active', '激活'),
    ('triggered', '已触发'),
    ('executed', '已执行'),
    ('cancelled', '已取消'),
]

class Portfolio(models.Model):
    """投资组合模型"""
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name='用户')
    name = models.CharField(max_length=100, verbose_name='组合名称')
    description = models.TextField(blank=True, verbose_name='组合描述')
    
    # 资产配置比例 (4:3:2:1)
    stable_ratio = models.DecimalField(max_digits=5, decimal_places=4, default=Decimal('0.40'), verbose_name='稳健型比例')
    balanced_ratio = models.DecimalField(max_digits=5, decimal_places=4, default=Decimal('0.30'), verbose_name='平衡型比例')
    growth_ratio = models.DecimalField(max_digits=5, decimal_places=4, default=Decimal('0.20'), verbose_name='成长型比例')
    aggressive_ratio = models.DecimalField(max_digits=5, decimal_places=4, default=Decimal('0.10'), verbose_name='进取型比例')
    
    # 投资金额
    total_amount = models.DecimalField(max_digits=15, decimal_places=2, verbose_name='总投资金额')
    current_value = models.DecimalField(max_digits=15, decimal_places=2, default=Decimal('0'), verbose_name='当前市值')
    
    # 状态
    status = models.CharField(max_length=20, choices=PORTFOLIO_STATUS, default='active', verbose_name='状态')
    
    # 时间戳
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    
    class Meta:
        verbose_name = '投资组合'
        verbose_name_plural = '投资组合'
        db_table = 'portfolios'
        ordering = ['-created_at']
    
    def __str__(self):
        return f'{self.user.username} - {self.name}'
    
    @property
    def total_return(self):
        """总收益"""
        try:
            if self.current_value is not None and self.total_amount is not None:
                return self.current_value - self.total_amount
            return Decimal('0')
        except (TypeError, ValueError, Exception):
            return Decimal('0')
    
    @property
    def return_rate(self):
        """收益率"""
        try:
            if self.total_amount and self.total_amount > 0:
                result = (self.current_value - self.total_amount) / self.total_amount
                # 确保结果是有效的decimal并进行量化
                if result.is_finite():
                    return result.quantize(Decimal('0.0001'))
            return Decimal('0')
        except (TypeError, ValueError, ZeroDivisionError, Exception):
            return Decimal('0')

class PortfolioHolding(models.Model):
    """投资组合持仓"""
    portfolio = models.ForeignKey(Portfolio, on_delete=models.CASCADE, verbose_name='投资组合')
    product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name='产品')
    
    # 持仓信息
    shares = models.DecimalField(max_digits=15, decimal_places=4, verbose_name='持有份额')
    cost_price = models.DecimalField(max_digits=10, decimal_places=4, verbose_name='成本价格')
    current_price = models.DecimalField(max_digits=10, decimal_places=4, verbose_name='当前价格')
    
    # 金额信息
    cost_amount = models.DecimalField(max_digits=15, decimal_places=2, verbose_name='成本金额')
    current_amount = models.DecimalField(max_digits=15, decimal_places=2, verbose_name='当前金额')
    
    # 时间戳
    purchase_date = models.DateTimeField(verbose_name='购买时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    
    class Meta:
        verbose_name = '投资组合持仓'
        verbose_name_plural = '投资组合持仓'
        db_table = 'portfolio_holdings'
        unique_together = ['portfolio', 'product']
    
    def __str__(self):
        return f'{self.portfolio.name} - {self.product.name}'
    
    @property
    def profit_loss(self):
        """盈亏金额"""
        try:
            if self.current_amount is not None and self.cost_amount is not None:
                return self.current_amount - self.cost_amount
            return Decimal('0')
        except (TypeError, ValueError, Exception):
            return Decimal('0')
    
    @property
    def profit_loss_rate(self):
        """盈亏比例"""
        try:
            if self.cost_amount and self.cost_amount > 0:
                result = (self.current_amount - self.cost_amount) / self.cost_amount
                # 确保结果是有效的decimal并进行量化
                if result.is_finite():
                    return result.quantize(Decimal('0.0001'))
            return Decimal('0')
        except (TypeError, ValueError, ZeroDivisionError, Exception):
            return Decimal('0')

class StopLossSetting(models.Model):
    """止损设置"""
    portfolio = models.ForeignKey(Portfolio, on_delete=models.CASCADE, verbose_name='投资组合')
    product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name='产品')
    
    # 止损策略
    strategy_type = models.CharField(max_length=20, choices=STOP_LOSS_STRATEGIES, verbose_name='止损策略')
    
    # 固定比例止损参数
    stop_loss_ratio = models.DecimalField(max_digits=5, decimal_places=4, null=True, blank=True, verbose_name='止损比例')
    purchase_price = models.DecimalField(max_digits=10, decimal_places=4, null=True, blank=True, verbose_name='买入价格')
    stop_loss_price = models.DecimalField(max_digits=10, decimal_places=4, null=True, blank=True, verbose_name='止损价格')
    
    # 移动止损参数
    trailing_distance = models.DecimalField(max_digits=5, decimal_places=4, null=True, blank=True, verbose_name='跟踪距离')
    highest_price = models.DecimalField(max_digits=10, decimal_places=4, null=True, blank=True, verbose_name='最高价格')
    
    # 技术指标止损参数
    technical_indicator = models.CharField(max_length=20, null=True, blank=True, verbose_name='技术指标')
    indicator_params = models.JSONField(null=True, blank=True, verbose_name='指标参数')
    
    # 执行设置
    auto_execute = models.BooleanField(default=False, verbose_name='自动执行')
    status = models.CharField(max_length=20, choices=STOP_LOSS_STATUS, default='active', verbose_name='状态')
    
    # 时间戳
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    triggered_at = models.DateTimeField(null=True, blank=True, verbose_name='触发时间')
    
    class Meta:
        verbose_name = '止损设置'
        verbose_name_plural = '止损设置'
        db_table = 'stop_loss_settings'
    
    def __str__(self):
        return f'{self.portfolio.name} - {self.product.name} - {self.get_strategy_type_display()}'

class Transaction(models.Model):
    """交易记录"""
    TRANSACTION_TYPES = [
        ('buy', '买入'),
        ('sell', '卖出'),
        ('dividend', '分红'),
    ]
    
    portfolio = models.ForeignKey(Portfolio, on_delete=models.CASCADE, verbose_name='投资组合')
    product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name='产品')
    
    transaction_type = models.CharField(max_length=20, choices=TRANSACTION_TYPES, verbose_name='交易类型')
    shares = models.DecimalField(max_digits=15, decimal_places=4, verbose_name='交易份额')
    price = models.DecimalField(max_digits=10, decimal_places=4, verbose_name='交易价格')
    amount = models.DecimalField(max_digits=15, decimal_places=2, verbose_name='交易金额')
    fee = models.DecimalField(max_digits=10, decimal_places=2, default=Decimal('0'), verbose_name='手续费')
    
    transaction_date = models.DateTimeField(verbose_name='交易时间')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    
    class Meta:
        verbose_name = '交易记录'
        verbose_name_plural = '交易记录'
        db_table = 'transactions'
        ordering = ['-transaction_date']
    
    def __str__(self):
        return f'{self.portfolio.name} - {self.get_transaction_type_display()} - {self.product.name}'
